
package com.work.util;

import java.io.*;
import java.net.URL;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.work.i18n.Messages;

public class AppUtils {

	public final static long SECOND_MILLIS = 1000;
	public final static long MINUTE_MILLIS = SECOND_MILLIS * 60;
	public final static long HOUR_MILLIS = MINUTE_MILLIS * 60;
	public final static long DAY_MILLIS = HOUR_MILLIS * 24;
	public final static long YEAR_MILLIS = DAY_MILLIS * 365;

	public static ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

	public static final String SCHEMA_PATH = "xsd/";
	public static final String XML_PATH = "xml/";

	public static URL getUrl(String resourcePath)
	{
		return classLoader.getResource(resourcePath);
	}

	public static File getSchemaFile(String xsdName) throws FileNotFoundException
	{
		return getFile(SCHEMA_PATH + xsdName);
	}

	public static File getXmlFile(String xmlName) throws IOException
	{
		return getFile(XML_PATH + xmlName);
	}

	public static File getFile(String path) throws FileNotFoundException
	{
		URL url = getUrl(path);

		if (url == null) {
			throw new FileNotFoundException("Plik '" + path + "' nie istnieje!");
		}

		return new File(url.getPath());
	}

	public static String getSchemasPath()
	{
		return getUrl(SCHEMA_PATH).getPath();
	}

	public static Date createDate(int year, int month, int day)
	{
		Calendar cal = Calendar.getInstance();
		cal.set(year, month - 1, day);

		return cal.getTime();
	}

	public static Time getDifferenceBeetwenTime(Time dateTo, Time dateFrom)
	{
		try {
			long diff = dateTo.getTime() - dateFrom.getTime();
			double differenceInHours = diff / ((double) 1000 * 60 * 60);
			double differenceInMinutes = (differenceInHours - (int) differenceInHours) * 60;
			double differenceInSeconds = (differenceInMinutes - (int) differenceInMinutes) * 60;

			return AppUtils.createTime((int) differenceInHours, (int) differenceInMinutes, (int) differenceInSeconds);
		} catch (Exception e) {

		}
		return AppUtils.createTime(0, 0, 0);
	}

	public static int getDifferenceInMunutes(Time dateTo, Time dateFrom)
	{
		try {
			if (dateFrom == null || dateTo == null)
				return 0;

			return (int) ((dateTo.getTime() / MINUTE_MILLIS) - (dateFrom.getTime() / MINUTE_MILLIS));
		} catch (Exception e) {

		}
		return 0;
	}

	public static Time createTime(long timeInMiliseconds)
	{
		try {
			double timeInHours = timeInMiliseconds / ((double) 1000 * 60 * 60);
			double timeInMinutes = (timeInHours - (int) timeInHours) * 60;
			double timeInSeconds = (timeInMinutes - (int) timeInMinutes) * 60;

			return AppUtils.createTime((int) timeInHours, (int) timeInMinutes, (int) timeInSeconds);
		} catch (Exception e) {

		}
		return AppUtils.createTime(0, 0, 0);
	}

	public static Time createTime(int hour, int minute, int second)
	{
		Time time = Time.valueOf(String.valueOf(hour) + ":" + String.valueOf(minute) + ":" + String.valueOf(second));
		return time;
	}

	public static boolean checkWeekend(Date date)
	{
		if (checkDay(date, Calendar.SATURDAY) || checkDay(date, Calendar.SUNDAY)) {
			return true;
		}

		return false;
	}

	public static boolean checkDay(Date date, int day)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);

		int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);

		if (dayOfWeek == day) {
			return true;
		}

		return false;
	}

	public static String getMonthName(Date month)
	{
		return MonthsEnum.getName(getMonthId(month));
	}

	public static int getMonthId(Date date)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int monthId = calendar.get(Calendar.MONTH);

		return monthId;
	}

	public static int getMonthDaysCount(Date month)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(month);
		return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	public static Integer getIntFromString(String text)
	{
		Integer number = null;

		try {
			number = Integer.valueOf(text);
		} catch (Exception e) {
		}

		return number;
	}

	public static Pair<Date, Date> getLastAndFirstDayOfYear(int year)
	{
		Calendar calendar = Calendar.getInstance();

		calendar.set(year, 0, 1, 0, 0);
		Date firstDayOfYear = calendar.getTime();

		calendar.set(year, 11, 31, 23, 59);
		Date lastDayOfYear = calendar.getTime();

		return new Pair<Date, Date>(firstDayOfYear, lastDayOfYear);
	}

	public static String convertMinutesToTimeString(int minutes)
	{
		int hourPart = (int) minutes / 60;
		int minutePart = minutes - (hourPart * 60);
		return hourPart + " h " + minutePart + " min";
	}

	public static String convertMinutesToTimeString(String minutesString)
	{
		int minutes = Integer.parseInt(minutesString);
		return convertMinutesToTimeString(minutes);
	}

	public static String formatDate(Date date)
	{
		return formatDate(date, "yyyy-MM-dd");
	}

	public static String formatDate(Date date, String formatPattern)
	{
		SimpleDateFormat df = new SimpleDateFormat(formatPattern);
		return df.format(date);
	}

	public static String getDaysCountDescription(int daysCount)
	{
		StringBuilder sb = new StringBuilder();
		sb.append(String.valueOf(daysCount));
		sb.append(AppConstants.SPACE);

		if (daysCount == 1) {
			sb.append(Messages.get("dzien"));
		} else {
			sb.append(Messages.get("dni"));
		}

		return sb.toString();
	}

	public static boolean areTimesOrdered(Time... times)
	{
		boolean timesOrdered = true;
		for (int i = 0; i < times.length; i++) {
			for (int j = 0 + i; j < times.length; j++) {
				if (times[j].before(times[i])) {
					timesOrdered = false;
				}
			}
		}

		return timesOrdered;
	}

	public static boolean areTimesEmpty(Time... times)
	{
		boolean allEmpty = true;

		for (Time time : times) {
			if (time.compareTo(createTime(0, 0, 0)) != 0) {
				allEmpty = false;
			}
		}

		return allEmpty;
	}

	public static boolean checkTimeDifference(Time timeFrom, Time timeTo, int timeUnit, int timeLength)
	{
		double timeFromPart = getTimePart(timeFrom, timeUnit);
		double timeToPart = getTimePart(timeTo, timeUnit);
		double difference = timeToPart - timeFromPart;
		if (difference > timeLength) {
			return false;
		}
		return true;
	}

	public static double getTimePart(Time time, int timeUnit)
	{
		if (Calendar.HOUR == timeUnit) {
			return TimeUnit.MILLISECONDS.toHours(time.getTime());
		} else if (Calendar.MINUTE == timeUnit) {
			return TimeUnit.MILLISECONDS.toMinutes(time.getTime());
		} else if (Calendar.SECOND == timeUnit) {
			return TimeUnit.MILLISECONDS.toSeconds(time.getTime());
		}

		return 0;
	}

	public static boolean checkNull(Object... objects)
	{
		for (Object object : objects) {
			if (object == null) {
				return false;
			}
		}
		return true;
	}

	public static int calculatePresentsTime(Time workBegin, Time lunchBegin, Time lunchEnd, Time workEnd)
	{
		if (AppUtils.checkNull(workBegin, workEnd, lunchBegin, lunchEnd)) {
			long lunch = lunchEnd.getTime() - lunchBegin.getTime();
			long timeInWork = workEnd.getTime() - workBegin.getTime();
			return (int) ((timeInWork - lunch) / AppUtils.MINUTE_MILLIS);
		}
		return 0;
	}

	public static int calculateOvertime(Time overtimeBegin, Time overtimeEnd)
	{
		if (AppUtils.checkNull(overtimeBegin, overtimeEnd)) {
			long overtime = overtimeEnd.getTime() - overtimeBegin.getTime();
			return (int) (overtime / AppUtils.MINUTE_MILLIS);
		}
		return 0;
	}

	public static int getYear(Date date)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int yearId = calendar.get(Calendar.YEAR);

		return yearId;
	}

	public static Date getFirstDayOfMonth(int year, int month)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.set(year, month, 1);
		
		return calendar.getTime();
	}

	public static Date getLastDayOfMonth(Date date)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
		calendar.set(Calendar.DAY_OF_MONTH, lastDay);
		
		return calendar.getTime();
	}
}
